package com.athena.framework.beanfactory;

import cn.hutool.core.lang.Assert;
import com.athena.framework.exception.BeanException;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;

public class DefaultBeanFactory implements BeanFactory {
    /**
     * 所有被托管的类
     */
    private static final Map<String, Object> beans = new ConcurrentHashMap<>();

    private static BeanFactory beanFactory;

    private DefaultBeanFactory() {
    }


    /**
     * 获取BeanFactory
     *
     * @return
     */
    public static BeanFactory creatBeanFactory() {
        if (beanFactory == null) {
            DefaultBeanFactory.beanFactory = new DefaultBeanFactory();
        }
        return DefaultBeanFactory.beanFactory;
    }

    @Override
    public void addBean(Object object) {
        //获取class全名称
        String name = object.getClass().getName();
        addBean(name, object);
    }

    @Override
    public synchronized void addBean(String beanName, Object object) {
        if (getBean(beanName) != null) {
            throw new BeanException("新添加的bean的名称不是唯一的！！！");
        }
        //设置cglib代理对象

        beans.put(beanName, object);
    }

    @Override
    public <T> T getBean(Class<T> clazz) {
        return (T) getBean(clazz.getName());
    }

    @Override
    public Object getBean(String beanName) {
        return beans.get(beanName);
    }

    @Override
    public <T> List<T> findBeanByClass(Class<T> clazz) {
        List<T> list = new LinkedList<>();
        beans.forEach((name, bean) -> {
            if (bean.getClass() == clazz) {
                list.add((T) bean);
            }
        });
        return list.size() == 0 ? null : list;
    }

    /**
     * 遍历被托管的类
     *
     * @param action
     */
    @Override
    public void forEach(BiConsumer<String, Object> action) {
        beans.forEach(action);
    }

    /**
     * 查找其子类或实现类
     *
     * @param type
     * @return
     */
    @Override
    public Map<String,Object> findSubclass(Class<?> type) {
        Map<String,Object> map=new HashMap<>();
        beans.forEach((name, obj) -> {
            if (obj.getClass().isAssignableFrom(type)){
                map.put(name,obj);
            }
        });
        return map;
    }

    @Override
    public Set<String> getKeySet() {
        return beans.keySet();
    }

    @Override
    public void setBean(String key, Object bean) {
        Assert.notNull(bean);
        beans.put(key,bean);
    }
}
